package datos;

import VistaConexion.Usuario;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import java.sql.*;

/**
 *
 * @author Steven Van Puelsy
 */
public class MetodoEstadistico {

    public ArrayList<Integer> ubicacion;//Contiene la las columnas donde faltan valores 
    public ArrayList<ArrayList<String>> tabla;//Tabla con todos los datos
    public ArrayList<ArrayList<String>> tabla2;//Tabla sin datos vacios
    public ArrayList<ArrayList<String>> eliminados;// contiene los valores eliminados de tabla
    public ArrayList<ArrayList<Integer>> vacios;//en la posicion 0 tiene el ubicacion en la fila y la posicion 1 tiene la columna
    public ArrayList<ArrayList<String>> valoresAcalcular;//Tabla con los valores faltantes a calcular dentro de las bases de datos
    public ArrayList<ArrayList<Integer>> cantidadValorACalcular;//cantidad de estos valores
    public ArrayList<ArrayList<ArrayList<ArrayList<Double>>>> tabla3;//Cantidad de Valores de cada columna con respecto a las variables a predecir dividido entre la cantidad de cada valor a predecir
    public ArrayList<ArrayList<String>> tabla4;//Valores de cada columna
    public ArrayList<Double> sum;
    public double porcentaje;
    public Usuario info;
    public java.sql.Connection conexion;
    public String db = new String(); //DataBase;
    private String query;
    public ArrayList<String> campos = new ArrayList<String>();
    public ArrayList<String> tablas = new ArrayList<String>();
    public boolean me;

    public MetodoEstadistico(ArrayList<ArrayList<String>> tabla, Usuario u, String db, ArrayList<String> campos, ArrayList<String> tablas) {
        this.tablas = tablas;
        this.campos = campos;
        info = u;
        this.db = db;
        this.query = "";
        //this.tabla = tabla;
        this.tabla = (ArrayList<ArrayList<String>>) tabla.clone();
        do {
            double p = 0;
            this.porcentaje = 0;
            this.ubicacion = new ArrayList<Integer>();
            do {
                try {
                    p = Double.parseDouble(JOptionPane.showInputDialog("Porcentaje de aceptacion para rellenado "));
                    this.porcentaje = p;
                } catch (Exception e) {
                }
            } while (p > 100 || p < 0);
            this.eliminados = new ArrayList<ArrayList<String>>();
            this.vacios = new ArrayList<ArrayList<Integer>>();
            this.vacios = this.BuscaIndexVacios(this.tabla);
            this.tabla2 = this.eliminaVacios(tabla, this.vacios);
            this.valoresAcalcular = this.buscaValoresACalcualar(tabla2, vacios);
            this.cantidadValorACalcular = new ArrayList<ArrayList<Integer>>();
            this.tabla3 = new ArrayList<ArrayList<ArrayList<ArrayList<Double>>>>();
            this.tabla4 = new ArrayList<ArrayList<String>>();
            this.tabla4 = this.valoresColumnas(tabla2);
            this.cantidadValorACalcular = this.contadordeBD(valoresAcalcular, tabla2);
            this.tabla3 = matrizGeneral();
            me = this.matrizOrganizada();
            tabla = (ArrayList<ArrayList<String>>) this.tabla.clone();
        } while (me);

    }

    public void acualizaTabla(ArrayList<String> valores, String value, int z) {
        try {
            conexion = DriverManager.getConnection(info.getUrl() + db, info.getUser(), info.getPassword());
            String queryMinable = "";

            if (query.equalsIgnoreCase("")) {
                queryMinable += "UPDATE ";
                for (int i = 0; i < tablas.size(); i++) {
                    queryMinable += tablas.get(i);
                    if (i != tablas.size() - 1) {
                        queryMinable += ", ";
                    }
                }
                queryMinable += " SET " + campos.get(z) + " = '" + value + "'";
                queryMinable += " WHERE ";
                for (int i = 0; i < valores.size(); i++) {
                    queryMinable += campos.get(i) + " = " + "'" + valores.get(i) + "'";
                    if (i != campos.size() - 1) {
                        queryMinable += " AND ";
                    }

                }
            } else {
                queryMinable = this.query;
            }
            System.out.print("\n" + queryMinable + "\n");
            PreparedStatement updateQuery = conexion.prepareStatement(queryMinable);
            updateQuery.executeUpdate();
            conexion.close();

        } catch (SQLException ex) {
            System.out.println("clase Minar: " + ex.toString());
            JOptionPane.showMessageDialog(null, "Escriba una sentencia SQL valida");
        }
    }

    public void regresaBool(ArrayList<String> valores) {
        try {
            conexion = DriverManager.getConnection(info.getUrl() + db, info.getUser(), info.getPassword());
            String queryMinable = "";

            if (query.equalsIgnoreCase("")) {
                queryMinable += "SELECT ";
                for (int i = 0; i < campos.size(); i++) {
                    queryMinable += campos.get(i);
                    if (i != campos.size() - 1) {
                        queryMinable += ", ";
                    }
                }

                queryMinable += " FROM ";

                for (int i = 0; i < tablas.size(); i++) {
                    queryMinable += tablas.get(i);
                    if (i != tablas.size() - 1) {
                        queryMinable += ", ";
                    }
                }

                queryMinable += " WHERE ";
                for (int i = 0; i < campos.size(); i++) {
                    queryMinable += campos.get(i) + " != '' ";
                    if (i != campos.size() - 1) {
                        queryMinable += " AND ";
                    }
                }
                int h = (int) (tabla.size() * 0.3);
                queryMinable += " ORDER BY RAND() DESC LIMIT 0 , " + h;
            } else {
                queryMinable = this.query;
            }

            System.out.print("\n" + queryMinable + "\n");

            Statement createStatement = conexion.createStatement();

            ResultSet resultCampos = createStatement.executeQuery(queryMinable);

            String[] tipoDatos = new String[campos.size()];
            for (int i = 0; i < tipoDatos.length; i++) {
                tipoDatos[i] = "integer";
            }
            while (resultCampos.next()) {

                ArrayList< String> fila = new ArrayList<String>();

                for (int i = 1; i <= campos.size(); i++) {

                    if (resultCampos.getString(i) != null) {

                        fila.add(resultCampos.getString(i));

                        String valor = resultCampos.getString(i);

                        for (int a = 0; a < valor.length(); a++) {
                            char c = valor.charAt(a);
                            if (c == '-') {
                                tipoDatos[i - 1] = "date";
                            } else if (c == ',' || c == '.') {
                                tipoDatos[i - 1] = "float";
                            } else if (c < '0' || c > '9') {
                                tipoDatos[i - 1] = "string";
                            }
                        }
                    } else {
                        fila.add("null");
                    }
                }

                for (int i = 0; i < fila.size(); i++) {
                    if ("null".equals(fila.get(i))) {
                        if ("integer".equals(tipoDatos[i])) {
                            fila.set(i, "0");
                        } else if ("date".equals(tipoDatos[i])) {
                            fila.set(i, "1-1-1900");
                        } else if ("float".equals(tipoDatos[i])) {
                            fila.set(i, "0,0");
                        } else if ("string".equals(tipoDatos[i])) {
                            fila.set(i, "ninguno");
                        }
                    }
                }

                tabla.add(fila);
            }

            createStatement.close();
            conexion.close();

        } catch (SQLException ex) {
            System.out.println("clase Minar: " + ex.toString());
            JOptionPane.showMessageDialog(null, "Escriba una sentencia SQL valida");
        }
    }

    public boolean matrizOrganizada() {
        ArrayList<ArrayList<Double>> asd = new ArrayList<ArrayList<Double>>();
        ArrayList<Double> das = new ArrayList<Double>();

        for (int d = 0; d < cantidadValorACalcular.size(); d++) {
            das = new ArrayList<Double>();
            double sumatoria = 0;
            for (int e = 0; e < cantidadValorACalcular.get(d).size(); e++) {
                sumatoria += cantidadValorACalcular.get(d).get(e);
            }

            for (int e = 0; e < cantidadValorACalcular.get(d).size(); e++) {
                das.add(cantidadValorACalcular.get(d).get(e) / sumatoria);
            }
            System.out.print("\nSumatoria = " + das + "\n");
            asd.add(das);
        }
        ArrayList<Double> pp;
        ArrayList<String> ss;
        for (int i = 0; i < this.eliminados.size(); i++) {
            for (int k = 0; k < valoresAcalcular.size(); k++) {
                pp = new ArrayList<Double>();
                ss = new ArrayList<String>();
                for (int l = 0; l < this.valoresAcalcular.get(k).size(); l++) {
                    double sumatoria = 1;
                    String suma = "";
                    for (int m = 0; m < this.tabla4.size(); m++) {
                        for (int x = 0; x < this.eliminados.get(i).size(); x++) {
                            if (!this.eliminados.get(i).get(x).isEmpty()) {
                                for (int z = 0; z < this.tabla4.get(vacios.get(i).get(1)).size(); z++) {
                                    for (int o = 0; o < this.tabla4.get(m).size(); o++) {
                                        if (tabla4.get(vacios.get(i).get(1)).get(z).equals(valoresAcalcular.get(k).get(l))) {
                                            if (tabla4.get(m).get(o).equals(eliminados.get(i).get(x))) {
                                                sumatoria *= tabla3.get(k).get(l).get(m).get(o);
                                                suma = valoresAcalcular.get(k).get(l);
                                            }
                                        }
                                    }
                                }
                            }

                        }
                    }
                    sumatoria *= asd.get(k).get(l);
                    pp.add(sumatoria);
                    ss.add(suma);
                }
                double a = 0;
                int s = 0;//Tengo la posicion
                double sumat = 0;
                for (int h = 0; h < pp.size(); h++) {
                    sumat += pp.get(h);
                }
                for (int h = 0; h < pp.size(); h++) {
                    pp.set(h, (pp.get(h) / sumat) * 100);
                }
                for (int h = 0; h < pp.size(); h++) {
                    if (pp.get(h) > a) {
                        a = pp.get(h);
                        s = h;
                    }
                }
                ArrayList<String> c = eliminados.get(i);
                String qwe;
                do {
                    qwe = JOptionPane.showInputDialog("Desea ultilizar el metodo de relleno de BD (s/n)");
                } while (!qwe.equals("s") && !qwe.equals("n") && !qwe.equals("S") && !qwe.equals("N") && !qwe.equals("si") && !qwe.equals("no")
                        && !qwe.equals("NO") && !qwe.equals("SI") && !qwe.equals("No") && !qwe.equals("Si") && !qwe.equals("sI") && !qwe.equals("nO"));
                if (a < this.porcentaje) {
                    if (qwe.equals("S") || qwe.equals("SI") || qwe.equals("s") || qwe.equals("Si") || qwe.equals("si") || qwe.equals("sI")) {
                        regresaBool(c);
                        System.out.print("\nAqui parte");
                        return true;
                    }
                } else {
                    if (qwe.equals("S") || qwe.equals("SI") || qwe.equals("s") || qwe.equals("Si") || qwe.equals("si") || qwe.equals("sI")) {
                        int aa = vacios.get(i).get(1);
                        for (int www = 0; www < tabla.get(vacios.get(i).get(1)).size(); www++) {
                            if (tabla.get(vacios.get(i).get(1)).get(www).isEmpty()) {
                                tabla.get(vacios.get(i).get(1)).set(www, valoresAcalcular.get(k).get(s));
                            }
                        }
                        acualizaTabla(c, ss.get(s), aa);
                    }
                }
            }
        }
        return false;
    }

    public ArrayList<ArrayList<ArrayList<ArrayList<Double>>>> matrizGeneral() {
        ArrayList<ArrayList<ArrayList<ArrayList<Double>>>> ww = new ArrayList<ArrayList<ArrayList<ArrayList<Double>>>>();
        for (int i = 0; i < valoresAcalcular.size(); i++) {
            ArrayList<ArrayList<ArrayList<Double>>> ee = new ArrayList<ArrayList<ArrayList<Double>>>();
            for (int j = 0; j < valoresAcalcular.get(i).size(); j++) {
                ArrayList<ArrayList<Double>> kk = new ArrayList<ArrayList<Double>>();
                for (int k = 0; k < tabla4.size(); k++) {
                    ArrayList<Double> pp = new ArrayList<Double>();
                    for (int l = 0; l < tabla4.get(k).size(); l++) {
                        double suma = 0;
                        for (int m = 0; m < tabla2.size(); m++) {
                            if (tabla2.get(m).contains(valoresAcalcular.get(i).get(j)) && tabla2.get(m).contains(tabla4.get(k).get(l))) {
                                suma++;
                            }
                        }
                        pp.add(suma / cantidadValorACalcular.get(i).get(j));
                    }
                    kk.add(pp);
                }
                ee.add(kk);
            }
            ww.add(ee);
        }
        return ww;
    }

    public ArrayList<ArrayList<Integer>> contadordeBD(ArrayList<ArrayList<String>> valoresAcalcular, ArrayList<ArrayList<String>> tabla2) {
        ArrayList<ArrayList<Integer>> cantidadvalorACalcular = new ArrayList<ArrayList<Integer>>();
        for (ArrayList<String> hola : valoresAcalcular) {
            ArrayList<Integer> pp = new ArrayList<Integer>();
            for (String k : hola) {
                int Sumatoria = 0;
                for (ArrayList<String> p : tabla2) {
                    if (p.contains(k)) {
                        Sumatoria++;
                    }
                }
                pp.add(Sumatoria);
            }
            cantidadvalorACalcular.add(pp);
        }
        return cantidadvalorACalcular;
    }

    public ArrayList<ArrayList<String>> valoresColumnas(ArrayList<ArrayList<String>> tabla2) {
        ArrayList<ArrayList<String>> p = new ArrayList<ArrayList<String>>();
        ArrayList<String> k;
        for (int j = 0; j < tabla2.get(0).size(); j++) {
            k = new ArrayList<String>();
            for (int i = 0; i < tabla2.size(); i++) {
                if (!k.contains(tabla2.get(i).get(j))) {
                    k.add(tabla2.get(i).get(j));
                }
            }
            p.add(k);
        }
        return p;
    }

    public ArrayList<ArrayList<String>> buscaValoresACalcualar(ArrayList<ArrayList<String>> tabla2, ArrayList<ArrayList<Integer>> vacios) {
        ArrayList<ArrayList<String>> resultado = new ArrayList<ArrayList<String>>();
        ArrayList<String> parcial;
        ArrayList<String> total = new ArrayList<String>();
        for (ArrayList<Integer> w : vacios) {
            parcial = new ArrayList<String>();
            for (int i = 0; i < tabla2.size(); i++) {
                if (!total.contains(tabla2.get(i).get(w.get(1)))) {
                    parcial.add(tabla2.get(i).get(w.get(1)));
                    total.add(tabla2.get(i).get(w.get(1)));
                }
            }
            resultado.add(parcial);
        }
        return resultado;
    }

    public ArrayList<ArrayList<String>> eliminaVacios(ArrayList<ArrayList<String>> tabla, ArrayList<ArrayList<Integer>> vacios) {
        int i = 0;
        for (ArrayList<Integer> k : vacios) {
            ArrayList<String> j = tabla.remove((int) k.get(0) - i);
            //ArrayList<String> j = tabla.get((int) k.get(0) - i);
            this.eliminados.add(j);
            i++;
        }
        return tabla;
    }

    public ArrayList<ArrayList<Integer>> BuscaIndexVacios(ArrayList<ArrayList<String>> tabla) {
        ArrayList<ArrayList<Integer>> v = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> w;
        ArrayList<Integer> p = new ArrayList<Integer>();
        for (int i = 0; i < tabla.size(); i++) {
            for (int j = 0; j < tabla.get(i).size(); j++) {
                if (tabla.get(i).get(j).isEmpty() || tabla.get(i).get(j).equals("")) {
                    w = new ArrayList<Integer>();
                    w.add(i);
                    w.add(j);
                    v.add(w);
                    if (!this.ubicacion.contains(j)) {
                        this.ubicacion.add(j);
                    }
                }
            }
        }
        return v;
    }
}
